import 'dart:io';

import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
import 'package:upgrade/app_version.dart';
import 'package:upgrade/custom_exception.dart';
import 'package:upgrade/log_util.dart';
import 'package:upgrade/net/dio_client.dart';
import 'package:upgrade/upgrade_manager.dart';
import 'package:url_launcher/url_launcher.dart';

import 'upgrade_platform_interface.dart';

class UpgradeDialog extends StatefulWidget {
  const UpgradeDialog(this.versionList, this.options, {Key? key}) : super(key: key);

  final List<AppVersion> versionList;
  final UpgradeOptionBuilder options;

  @override
  State<UpgradeDialog> createState() => _UpgradeDialogState();
}

class _UpgradeDialogState extends State<UpgradeDialog> {
  late File file;
  var tag = "UpgradeDialog";

  int downloadProgress = 0;
  var downloadState = DownloadState.notYetStarted;

  @override
  initState() {
    _getLocalFile();
    super.initState();
  }

  _getLocalFile() async {
    // 获取应用目录
    var directory = await getTemporaryDirectory();
    var dir = directory.path;
    var exist = await directory.exists();
    LogUtil.i(tag, "$dir exist = $exist");
    file = File('$dir/new.apk');
  }

  _install() {
    UpgradePlatform.instance.install(file.path);
  }

  _download(AppVersion version) {
    bool isSizeSame = false;
    downloadState = DownloadState.downloading;
    var url = "${widget.options.option.downloadHost}/distribute/app/down?fileId=${version.fileId}";
    LogUtil.i(tag, "download url = $url");
    dioClient.download(url, file.path, onReceiveProgress: (int completedSize, int totalSize) {
      if (totalSize == version.size) {
        isSizeSame = true;
      }
      try {
        int progress = ((completedSize / totalSize) * 100).toInt();
        widget.options.downloadProgressUpdateListener?.call(progress);
        LogUtil.i(tag, "已下载 $completedSize 总大小 = $totalSize");
        LogUtil.i(tag, "进度 $progress");
        downloadProgress = progress;
        if (progress >= 100) {
          widget.options.downloadFinishListener?.call(file.path);
        }
        setState(() {});
      } on Exception catch (e) {
        widget.options.doOnError?.call(CustomException.downloadException(e));
        LogUtil.i(tag, e.toString());
      }
    }).then((value) {
      if (value != null) {
        if (!isSizeSame) {
          //大小不一样，失败
          downloadState = DownloadState.downloadFailed;
          setState(() {});
          LogUtil.i(tag, widget.options.doOnError.toString());
          widget.options.doOnError
              ?.call(CustomException.downloadException(Exception("size is different")));
        } else {
          //成功
          downloadState = DownloadState.downloadCompleted;
          setState(() {});
          _install();
        }
      } else {
        //响应为空，失败
        downloadState = DownloadState.downloadFailed;
        setState(() {});
        widget.options.doOnError
            ?.call(CustomException.downloadException(Exception("response is null")));
        LogUtil.i(tag, "下载失败 error ： 响应为空");
      }
    }).onError((error, stackTrace) {
      downloadState = DownloadState.downloadFailed;
      setState(() {});
      widget.options.doOnError
          ?.call(CustomException.downloadException(Exception(error.toString())));
      LogUtil.i(tag, "下载失败 error ： $error");
      LogUtil.i(tag, "下载失败 stackTrace：$stackTrace");
    });
  }

  String _getDownloadStateText(bool isForce) {
    if (Platform.isIOS) {
      return "去更新";
    }
    switch (downloadState) {
      case DownloadState.downloading:
        return "下载中";
      case DownloadState.downloadCompleted:
        return "安装";
      case DownloadState.downloadPause:
        return "继续下载";
      case DownloadState.notYetStarted:
        if (isForce) {
          return "立即更新（必要更新）";
        } else {
          return "立即更新";
        }

      case DownloadState.downloadFailed:
        return "重新下载";
    }
  }

  Widget _buildRadiusContainer(Widget child) {
    return Container(
        padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 10),
        width: double.infinity,
        child: child);
  }

  Widget _buildButton(Color bgColor, String text, Function() onPressed,
      {Color? fgColor, BorderSide? side}) {
    return ElevatedButton(
        style: ElevatedButton.styleFrom(
          padding: const EdgeInsets.symmetric(vertical: 10),
          backgroundColor: bgColor,
          foregroundColor: fgColor,
          disabledBackgroundColor: Colors.grey,
          side: side,
          shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(5))),
        ),
        onPressed: onPressed,
        child: Text(text, style: const TextStyle(fontSize: 20)));
  }

  Widget _buildDownloadWidget(AppVersion version) {
    if (downloadState == DownloadState.notYetStarted ||
        downloadState == DownloadState.downloadCompleted ||
        downloadState == DownloadState.downloadFailed) {
      return _buildButton(
          const Color(0xFF3771FF), _getDownloadStateText(version.forceUpgrade ?? false), () {
        if (Platform.isIOS) {
          if (version.appstoreAddress != null) {
            var uri = Uri.parse(version.appstoreAddress!);
            launchUrl(uri);
          }
        } else if (Platform.isAndroid) {
          if (downloadState == DownloadState.downloadCompleted) {
            _install();
          } else {
            _download(version);
          }
        }
      }, side: BorderSide.none);
    } else if (downloadState == DownloadState.downloading) {
      return Container(
        clipBehavior: Clip.antiAlias,
        decoration: const BoxDecoration(
          color: Colors.white,
          borderRadius: BorderRadius.all(Radius.circular(5)),
        ),
        child: Stack(
          alignment: Alignment.center,
          children: [
            LinearProgressIndicator(
              // color: Colors.green,
              backgroundColor: Colors.grey.shade300,
              valueColor: const AlwaysStoppedAnimation(Color(0xFF3771FF)),
              minHeight: 40,
              value: downloadProgress / 100,
            ),
            Text(
              "$downloadProgress",
              style: const TextStyle(
                fontSize: 20,
                color: Colors.white,
              ),
            )
          ],
        ),
      );
    }
    return Container();
  }

  Widget _buildCancelWidget(AppVersion version) {
    return _buildButton(Colors.white, "下次再说", () {
      if (widget.options.cancelUpgradeListener != null) {
        widget.options.cancelUpgradeListener?.call(version.forceUpgrade ?? false);
      } else {
        Navigator.pop(context);
      }
    }, fgColor: Colors.grey, side: const BorderSide(width: 1, color: Color(0xFFDCDEE0)));
  }

  @override
  Widget build(BuildContext context) {
    var height = MediaQuery.of(context).size.height / 10 * 6;
    var width = height / 3 * 2;
    var version = widget.versionList.first;
    return Material(
      color: Colors.transparent,
      child: SizedBox(
          height: height,
          width: width,
          child: Stack(children: [
            Padding(
              padding: const EdgeInsets.only(top: 30, bottom: 30),
              child: Container(
                height: height - 30,
                width: width,
                color: Colors.white,
              ),
            ),
            Column(
              mainAxisAlignment: MainAxisAlignment.start,
              children: [
                const Image(image: AssetImage("images/bg.png", package: "upgrade")),
                Expanded(
                  child: Container(
                    decoration: const BoxDecoration(
                      color: Colors.white,
                      borderRadius: BorderRadius.all(Radius.circular(5)),
                    ),
                    padding: const EdgeInsets.symmetric(horizontal: 10),
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Expanded(
                          child: SingleChildScrollView(
                            child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
                              Text(
                                "${version.versionName}",
                                style: const TextStyle(
                                  fontSize: 20,
                                  color: Color(0xFF323233),
                                ),
                              ),
                              const Divider(),
                              Text(
                                "${version.description}",
                                style: const TextStyle(
                                  fontSize: 20,
                                  color: Color(0xFF323233),
                                ),
                              ),
                            ]),
                          ),
                        ),
                        _buildRadiusContainer(_buildDownloadWidget(version)),
                        _buildRadiusContainer(_buildCancelWidget(version)),
                      ],
                    ),
                  ),
                )
              ],
            ),
            SizedBox(
              width: double.infinity,
              child: Column(
                mainAxisSize: MainAxisSize.min,
                crossAxisAlignment: CrossAxisAlignment.center,
                children: [
                  SizedBox(height: height / 13),
                  const Text(
                    "发现新版本",
                    style: TextStyle(
                      fontSize: 30,
                      color: Colors.white,
                    ),
                  ),
                ],
              ),
            ),
          ])),
    );
  }
}

enum DownloadState { downloading, downloadCompleted, downloadPause, notYetStarted, downloadFailed }
